﻿using Ormon.HostLinkLib.FinsBase;
using Ormon.HostLinkLib.HostLinkBase;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Ormon.HostLinkLib
{
    public class HostLinkFinsDevice
    {
        //串口示例
        private SerialPort serialPort;
        public string PortName;

        /// <summary>
        /// 构造函数——HostLinkFinsDevice
        /// </summary>
        /// <param name="portName">端口名</param>
        /// <param name="baudRate">波特率</param>
        /// <param name="parity">奇偶校验</param>
        /// <param name="dataBits">数据位</param>
        /// <param name="stopBits">停止位</param>
        public HostLinkFinsDevice(string portName, int baudRate, Parity parity, int dataBits, StopBits stopBits)
        {
            serialPort = new SerialPort(portName, baudRate, parity, dataBits, stopBits);
            PortName = serialPort.PortName;
        }



        /// <summary>
        /// 端口开启
        /// </summary>
        public void Connect()
        {
            try
            {
                serialPort.Open();
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 端口关闭
        /// </summary>
        public void DisConnect()
        {
            try
            {
                serialPort.Close();
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 将字节列表转换成bool列表
        /// </summary>
        /// <param name="ByteList">输入的字节列表</param>
        /// <returns>转换得到的bool列表</returns>
        private static List<bool> ByteList_BoolList(List<byte> ByteList)
        {
            List<bool> BoolList = new List<bool>();
            List<byte> TempList = new List<byte>();
            for (int i = 0; i < ByteList.Count - 1; i += 2)
            {
                TempList = ByteList.GetRange(i, 2);
                if (TempList.SequenceEqual(new List<byte> { 0x30, 0x30 }))
                {
                    BoolList.Add(false);
                }
                else
                {
                    BoolList.Add(true);
                }
            }
            return BoolList;
        }

        /// <summary>
        /// 将ushort转换成4位的字节列表
        /// </summary>
        /// <param name="UshortValue">输入的ushort数值</param>
        /// <returns>转换得到的字节列表</returns>
        private static List<byte> Ushotr_X4String_ByteList(ushort UshortValue)
        {
            string StringValue = UshortValue.ToString("X4");

            return Encoding.ASCII.GetBytes(StringValue).ToList();
        }

        /// <summary>
        /// 将ushort转换成2位字节列表
        /// </summary>
        /// <param name="UshortValue">输入的ushort数值</param>
        /// <returns>转换得到的字节列表</returns>
        private static List<byte> Ushotr_X2String_ByteList(ushort UshortValue)
        {
            string StringValue = UshortValue.ToString("X2");

            return Encoding.ASCII.GetBytes(StringValue).ToList();
        }


        #region 同步方法


        /// <summary>
        /// FINS读取PLC内存指定区域方法
        /// </summary>
        /// <param name="IOMemoryAreaAdr">IO内存区域地址</param>
        /// <param name="finsFrameConfig">FINS帧参数设置</param>
        /// <param name="ReadCount">读取寄存器位数</param>
        /// <param name="UnitNO">单元号，默认"00"</param>
        /// <param name="ResponseWaitTime">回复时间(单位10ms)，默认0</param>
        /// <param name="connectType">连接方式，默认直连</param>
        /// <returns>ResponseData或EndCodeContent：正常情况：返回读取到的数值（字符串格式）；异常情况：返回结束代码含义（字符串格式）</returns>
        public FinsResult Read_MemoryArea(FinsIOMemoryAreaAddress IOMemoryAreaAdr, FinsFrameConfig finsFrameConfig, ushort ReadCount, string UnitNO = "00", string ResponseWaitTime = "0", FinsConnectTypeEnum connectType = FinsConnectTypeEnum.Directly_Connect)
        {
            try
            {
                string EndCodeContent = null;
                List<byte> CommandFrame = new List<byte> { 0x40 };
                List<byte> ResponseFrame = new List<byte>();
                List<byte> ResponseDataFrame = new List<byte>();
                List<byte> MemoryAreaCode = new List<byte>();


                bool Result_isSuccessed;
                string Result_resultMessage;
                string Result_commandFrame;
                string Result_responseFrame;


                //定义内存区域代码
                if (IOMemoryAreaAdr != null)
                {
                    switch (IOMemoryAreaAdr.AreaType)
                    {
                        case FinsMemoryAreaTypeEnum.CIOBit:
                            MemoryAreaCode = FinsMemoryAreaCode.MemoryAreaCode_CIOBit;
                            break;
                        case FinsMemoryAreaTypeEnum.CIOWord:
                            MemoryAreaCode = FinsMemoryAreaCode.MemoryAreaCode_CIOWord;
                            break;
                        case FinsMemoryAreaTypeEnum.WRBit:
                            MemoryAreaCode = FinsMemoryAreaCode.MemoryAreaCode_WRBit;
                            break;
                        case FinsMemoryAreaTypeEnum.WRWord:
                            MemoryAreaCode = FinsMemoryAreaCode.MemoryAreaCode_WRWord;
                            break;
                        case FinsMemoryAreaTypeEnum.HRBit:
                            MemoryAreaCode = FinsMemoryAreaCode.MemoryAreaCode_HRBit;
                            break;
                        case FinsMemoryAreaTypeEnum.HRWord:
                            MemoryAreaCode = FinsMemoryAreaCode.MemoryAreaCode_HRWord;
                            break;
                        case FinsMemoryAreaTypeEnum.DMBit:
                            MemoryAreaCode = FinsMemoryAreaCode.MemoryAreaCode_DMBit;
                            break;
                        case FinsMemoryAreaTypeEnum.DMWord:
                            MemoryAreaCode = FinsMemoryAreaCode.MemoryAreaCode_DMWord;
                            break;
                        default:
                            throw new Exception("选择内存区域出错");
                    }
                }
                else
                {
                    throw new Exception("IOMemoryAreaAdr参数不存在");
                }

                //单元号
                CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(UnitNO));
                //FA
                CommandFrame.AddRange(new List<byte> { 0x46, 0x41 });
                //等待时间
                CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(ResponseWaitTime));

                //增加内存Fins命令帧参数
                if (finsFrameConfig != null)
                {
                    switch (connectType)
                    {
                        case FinsConnectTypeEnum.Directly_Connect:
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.ICF));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.DA2));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.SA2));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.SID));
                            break;
                        case FinsConnectTypeEnum.NetWork:
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.ICF));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.RSV));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.GCT));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.DNA));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.DA1));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.DA2));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.SNA));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.SA1));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.SA2));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.SID));
                            break;
                        default:
                            throw new Exception("连接类型参数出错");
                    }
                }
                else
                {
                    throw new Exception("finsFrameConfig命令帧参数不存在");
                }

                //0101 读取代码
                CommandFrame.AddRange(new List<byte> { 0x30, 0x31, 0x30, 0x31 });
                //IO内存区域代码
                CommandFrame.AddRange(MemoryAreaCode);
                //内存起始(Word)地址
                CommandFrame.AddRange(Ushotr_X4String_ByteList(IOMemoryAreaAdr.WordAddress));
                //内存起始(Bit)地址
                CommandFrame.AddRange(Ushotr_X2String_ByteList(IOMemoryAreaAdr.BitAddress));
                //读取位数
                CommandFrame.AddRange(Ushotr_X4String_ByteList(ReadCount));
                //增加结束符，完成命令报文
                CommandFrame.AddRange(HostLinkCore.HostLinkEndCode(CommandFrame));

                //通信结果——命令帧
                Result_commandFrame = ASCIIEncoding.ASCII.GetString(CommandFrame.ToArray());

                //发送报文并获取回复报文
                ResponseFrame = HostLinkCore.HostLinkCommCore(serialPort, CommandFrame);

                Result_responseFrame = ASCIIEncoding.ASCII.GetString(ResponseFrame.ToArray());

                if (ResponseFrame != null)
                {
                    Result_isSuccessed = true;

                    //获取结束代码
                    switch (connectType)
                    {
                        case FinsConnectTypeEnum.Directly_Connect:
                            EndCodeContent = FinsEndCode.CatchEndCode(ResponseFrame, 19);
                            break;
                        case FinsConnectTypeEnum.NetWork:
                            EndCodeContent = FinsEndCode.CatchEndCode(ResponseFrame, 31);
                            break;
                        default:
                            throw new Exception("连接方式错误");
                    }
                    //返回通信结果（数据或NG信息）
                    if (EndCodeContent.Equals("0000"))
                    {
                        //确定通信结果信息
                        Result_resultMessage = "OK";
                        //确定回复的数据
                        switch (connectType)
                        {
                            case FinsConnectTypeEnum.Directly_Connect:
                                ResponseDataFrame = ResponseFrame.GetRange(23, ResponseFrame.Count - 27);
                                break;
                            case FinsConnectTypeEnum.NetWork:
                                ResponseDataFrame = ResponseFrame.GetRange(35, ResponseFrame.Count - 39);
                                break;
                            default:
                                throw new Exception("连接方式错误");
                        }
                        //确定数据类型并返回通信结果
                        if (IOMemoryAreaAdr.AreaType.Equals(FinsMemoryAreaTypeEnum.CIOBit) ||
                            IOMemoryAreaAdr.AreaType.Equals(FinsMemoryAreaTypeEnum.DMBit) ||
                            IOMemoryAreaAdr.AreaType.Equals(FinsMemoryAreaTypeEnum.WRBit) ||
                            IOMemoryAreaAdr.AreaType.Equals(FinsMemoryAreaTypeEnum.HRBit))
                        {
                            List<bool> Result_BoolList = ByteList_BoolList(ResponseDataFrame);
                            return new FinsResult(Result_isSuccessed, Result_resultMessage, Result_commandFrame, Result_responseFrame, Result_BoolList);
                        }
                        else
                        {
                            string Result_String = ASCIIEncoding.ASCII.GetString(ResponseDataFrame.ToArray());
                            return new FinsResult(Result_isSuccessed, Result_resultMessage, Result_commandFrame, Result_responseFrame, Result_String);
                        }
                    }
                    else
                    {
                        Result_resultMessage = EndCodeContent;
                        return new FinsResult(Result_isSuccessed, Result_resultMessage, Result_commandFrame, Result_responseFrame);
                    }

                }
                else
                {
                    Result_isSuccessed = false;
                    Result_resultMessage = "接收回复报文出错";
                    return new FinsResult(Result_isSuccessed, Result_resultMessage);
                }
            }
            catch (Exception)
            {
                throw;
            }
        }


        /// <summary>
        /// FINS写入PLC内存指定区域方法
        /// </summary>
        /// <param name="IOMemoryAreaAdr">IO内存区域地址</param>
        /// <param name="finsFrameConfig">FINS帧参数设置</param>
        /// <param name="WriteCount">写入寄存器位数</param>
        /// <param name="WriteData">读取寄存器位数</param>
        /// <param name="UnitNO">单元号，默认"00"</param>
        /// <param name="ResponseWaitTime">回复时间(单位10ms)，默认0</param>
        /// <param name="connectType">连接方式，默认直连</param>
        /// <returns>EndCodeContent：返回结束代码含义（字符串格式），"0000"代表无异常，其他均为异常</returns>
        public FinsResult Write_MemoryArea(FinsIOMemoryAreaAddress IOMemoryAreaAdr, FinsFrameConfig finsFrameConfig, ushort WriteCount, string WriteData, string UnitNO = "00", string ResponseWaitTime = "0", FinsConnectTypeEnum connectType = FinsConnectTypeEnum.Directly_Connect)
        {
            try
            {
                string EndCodeContent = null;
                List<byte> CommandFrame = new List<byte> { 0x40 };
                List<byte> ResponseFrame = new List<byte>();
                List<byte> MemoryAreaCode = new List<byte>();


                bool Result_isSuccessed;
                string Result_resultMessage;
                string Result_commandFrame;
                string Result_responseFrame;


                //定义内存区域代码
                if (IOMemoryAreaAdr != null)
                {
                    switch (IOMemoryAreaAdr.AreaType)
                    {
                        case FinsMemoryAreaTypeEnum.CIOBit:
                            MemoryAreaCode = FinsMemoryAreaCode.MemoryAreaCode_CIOBit;
                            break;
                        case FinsMemoryAreaTypeEnum.CIOWord:
                            MemoryAreaCode = FinsMemoryAreaCode.MemoryAreaCode_CIOWord;
                            break;
                        case FinsMemoryAreaTypeEnum.WRBit:
                            MemoryAreaCode = FinsMemoryAreaCode.MemoryAreaCode_WRBit;
                            break;
                        case FinsMemoryAreaTypeEnum.WRWord:
                            MemoryAreaCode = FinsMemoryAreaCode.MemoryAreaCode_WRWord;
                            break;
                        case FinsMemoryAreaTypeEnum.HRBit:
                            MemoryAreaCode = FinsMemoryAreaCode.MemoryAreaCode_HRBit;
                            break;
                        case FinsMemoryAreaTypeEnum.HRWord:
                            MemoryAreaCode = FinsMemoryAreaCode.MemoryAreaCode_HRWord;
                            break;
                        case FinsMemoryAreaTypeEnum.DMBit:
                            MemoryAreaCode = FinsMemoryAreaCode.MemoryAreaCode_DMBit;
                            break;
                        case FinsMemoryAreaTypeEnum.DMWord:
                            MemoryAreaCode = FinsMemoryAreaCode.MemoryAreaCode_DMWord;
                            break;
                        default:
                            throw new Exception("选择内存区域出错");
                    }
                }
                else
                {
                    throw new Exception("IOMemoryAreaAdr参数不存在");
                }

                //单元号
                CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(UnitNO));
                //FA
                CommandFrame.AddRange(new List<byte> { 0x46, 0x41 });
                //等待时间
                CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(ResponseWaitTime));

                //增加内存Fins命令帧参数
                if (finsFrameConfig != null)
                {
                    switch (connectType)
                    {
                        case FinsConnectTypeEnum.Directly_Connect:
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.ICF));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.DA2));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.SA2));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.SID));
                            break;
                        case FinsConnectTypeEnum.NetWork:
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.ICF));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.RSV));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.GCT));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.DNA));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.DA1));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.DA2));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.SNA));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.SA1));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.SA2));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.SID));
                            break;
                        default:
                            throw new Exception("连接类型参数出错");
                    }
                }
                else
                {
                    throw new Exception("finsFrameConfig命令帧参数不存在");
                }

                //0102 写入代码
                CommandFrame.AddRange(new List<byte> { 0x30, 0x31, 0x30, 0x32 });
                //IO内存区域代码
                CommandFrame.AddRange(MemoryAreaCode);
                //内存起始(Word)地址
                CommandFrame.AddRange(Ushotr_X4String_ByteList(IOMemoryAreaAdr.WordAddress));
                //内存起始(Bit)地址
                CommandFrame.AddRange(Ushotr_X2String_ByteList(IOMemoryAreaAdr.BitAddress));
                //写入位数
                CommandFrame.AddRange(Ushotr_X4String_ByteList(WriteCount));
                //写入数据
                if (WriteData.Equals(string.Empty) || WriteData.Equals(null))
                {
                    throw new Exception("未输入数值");
                }
                else
                {
                    CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(WriteData));
                }
                //增加结束符，完成命令报文
                CommandFrame.AddRange(HostLinkCore.HostLinkEndCode(CommandFrame));

                //通信结果——命令帧
                Result_commandFrame = ASCIIEncoding.ASCII.GetString(CommandFrame.ToArray());



                //获取回复报文
                ResponseFrame = HostLinkCore.HostLinkCommCore(serialPort, CommandFrame);

                Result_responseFrame = ASCIIEncoding.ASCII.GetString(ResponseFrame.ToArray());

                if (ResponseFrame != null)
                {
                    Result_isSuccessed = true;

                    //获取结束代码
                    switch (connectType)
                    {
                        case FinsConnectTypeEnum.Directly_Connect:
                            EndCodeContent = FinsEndCode.CatchEndCode(ResponseFrame, 19);
                            break;
                        case FinsConnectTypeEnum.NetWork:
                            EndCodeContent = FinsEndCode.CatchEndCode(ResponseFrame, 31);
                            break;
                        default:
                            throw new Exception("连接方式错误");
                    }
                    //返回通信结果（OK或NG信息）
                    if (EndCodeContent.Equals("0000"))
                    {
                        //确定通信结果信息
                        Result_resultMessage = "OK";
                        return new FinsResult(Result_isSuccessed, Result_resultMessage, Result_commandFrame, Result_responseFrame);
                    }
                    else
                    {
                        Result_resultMessage = EndCodeContent;
                        return new FinsResult(Result_isSuccessed, Result_resultMessage, Result_commandFrame, Result_responseFrame);
                    }
                }
                else
                {
                    Result_isSuccessed = false;
                    Result_resultMessage = "接收回复报文出错";
                    return new FinsResult(Result_isSuccessed, Result_resultMessage);
                }
            }
            catch (Exception)
            {
                throw;
            }
        }


        #endregion


        #region 异步方法

        /// <summary>
        /// FINS读取PLC内存指定区域方法（异步方法）
        /// </summary>
        /// <param name="IOMemoryAreaAdr">IO内存区域地址</param>
        /// <param name="finsFrameConfig">FINS帧参数设置</param>
        /// <param name="ReadCount">读取寄存器位数</param>
        /// <param name="UnitNO">单元号，默认"00"</param>
        /// <param name="ResponseWaitTime">回复时间(单位10ms)，默认0</param>
        /// <param name="connectType">连接方式，默认直连</param>
        /// <returns>ResponseData或EndCodeContent：正常情况：返回读取到的数值（字符串格式）；异常情况：返回结束代码含义（字符串格式）</returns>
        public async Task<FinsResult> Read_MemoryAreaAsync(FinsIOMemoryAreaAddress IOMemoryAreaAdr, FinsFrameConfig finsFrameConfig, ushort ReadCount, string UnitNO = "00", string ResponseWaitTime = "0", FinsConnectTypeEnum connectType = FinsConnectTypeEnum.Directly_Connect)
        {
            try
            {
                string EndCodeContent = null;
                List<byte> CommandFrame = new List<byte> { 0x40 };
                List<byte> ResponseFrame = new List<byte>();
                List<byte> ResponseDataFrame = new List<byte>();
                List<byte> MemoryAreaCode = new List<byte>();


                bool Result_isSuccessed;
                string Result_resultMessage;
                string Result_commandFrame;
                string Result_responseFrame;


                //定义内存区域代码
                if (IOMemoryAreaAdr != null)
                {
                    switch (IOMemoryAreaAdr.AreaType)
                    {
                        case FinsMemoryAreaTypeEnum.CIOBit:
                            MemoryAreaCode = FinsMemoryAreaCode.MemoryAreaCode_CIOBit;
                            break;
                        case FinsMemoryAreaTypeEnum.CIOWord:
                            MemoryAreaCode = FinsMemoryAreaCode.MemoryAreaCode_CIOWord;
                            break;
                        case FinsMemoryAreaTypeEnum.WRBit:
                            MemoryAreaCode = FinsMemoryAreaCode.MemoryAreaCode_WRBit;
                            break;
                        case FinsMemoryAreaTypeEnum.WRWord:
                            MemoryAreaCode = FinsMemoryAreaCode.MemoryAreaCode_WRWord;
                            break;
                        case FinsMemoryAreaTypeEnum.HRBit:
                            MemoryAreaCode = FinsMemoryAreaCode.MemoryAreaCode_HRBit;
                            break;
                        case FinsMemoryAreaTypeEnum.HRWord:
                            MemoryAreaCode = FinsMemoryAreaCode.MemoryAreaCode_HRWord;
                            break;
                        case FinsMemoryAreaTypeEnum.DMBit:
                            MemoryAreaCode = FinsMemoryAreaCode.MemoryAreaCode_DMBit;
                            break;
                        case FinsMemoryAreaTypeEnum.DMWord:
                            MemoryAreaCode = FinsMemoryAreaCode.MemoryAreaCode_DMWord;
                            break;
                        default:
                            throw new Exception("选择内存区域出错");
                    }
                }
                else
                {
                    throw new Exception("IOMemoryAreaAdr参数不存在");
                }

                //单元号
                CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(UnitNO));
                //FA
                CommandFrame.AddRange(new List<byte> { 0x46, 0x41 });
                //等待时间
                CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(ResponseWaitTime));

                //增加内存Fins命令帧参数
                if (finsFrameConfig != null)
                {
                    switch (connectType)
                    {
                        case FinsConnectTypeEnum.Directly_Connect:
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.ICF));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.DA2));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.SA2));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.SID));
                            break;
                        case FinsConnectTypeEnum.NetWork:
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.ICF));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.RSV));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.GCT));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.DNA));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.DA1));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.DA2));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.SNA));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.SA1));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.SA2));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.SID));
                            break;
                        default:
                            throw new Exception("连接类型参数出错");
                    }
                }
                else
                {
                    throw new Exception("finsFrameConfig命令帧参数不存在");
                }

                //0101 读取代码
                CommandFrame.AddRange(new List<byte> { 0x30, 0x31, 0x30, 0x31 });
                //IO内存区域代码
                CommandFrame.AddRange(MemoryAreaCode);
                //内存起始(Word)地址
                CommandFrame.AddRange(Ushotr_X4String_ByteList(IOMemoryAreaAdr.WordAddress));
                //内存起始(Bit)地址
                CommandFrame.AddRange(Ushotr_X2String_ByteList(IOMemoryAreaAdr.BitAddress));
                //读取位数
                CommandFrame.AddRange(Ushotr_X4String_ByteList(ReadCount));
                //增加结束符，完成命令报文
                CommandFrame.AddRange(HostLinkCore.HostLinkEndCode(CommandFrame));

                //通信结果——命令帧
                Result_commandFrame = ASCIIEncoding.ASCII.GetString(CommandFrame.ToArray());

                //发送报文并获取回复报文
                ResponseFrame = await HostLinkCore.HostLinkCommCoreAsync(serialPort, CommandFrame);

                Result_responseFrame = ASCIIEncoding.ASCII.GetString(ResponseFrame.ToArray());

                if (ResponseFrame != null)
                {
                    Result_isSuccessed = true;

                    //获取结束代码
                    switch (connectType)
                    {
                        case FinsConnectTypeEnum.Directly_Connect:
                            EndCodeContent = FinsEndCode.CatchEndCode(ResponseFrame, 19);
                            break;
                        case FinsConnectTypeEnum.NetWork:
                            EndCodeContent = FinsEndCode.CatchEndCode(ResponseFrame, 31);
                            break;
                        default:
                            throw new Exception("连接方式错误");
                    }
                    //返回通信结果（数据或NG信息）
                    if (EndCodeContent.Equals("0000"))
                    {
                        //确定通信结果信息
                        Result_resultMessage = "OK";
                        //确定回复的数据
                        switch (connectType)
                        {
                            case FinsConnectTypeEnum.Directly_Connect:
                                ResponseDataFrame = ResponseFrame.GetRange(23, ResponseFrame.Count - 27);
                                break;
                            case FinsConnectTypeEnum.NetWork:
                                ResponseDataFrame = ResponseFrame.GetRange(35, ResponseFrame.Count - 39);
                                break;
                            default:
                                throw new Exception("连接方式错误");
                        }
                        //确定数据类型并返回通信结果
                        if (IOMemoryAreaAdr.AreaType.Equals(FinsMemoryAreaTypeEnum.CIOBit) ||
                            IOMemoryAreaAdr.AreaType.Equals(FinsMemoryAreaTypeEnum.DMBit) ||
                            IOMemoryAreaAdr.AreaType.Equals(FinsMemoryAreaTypeEnum.WRBit) ||
                            IOMemoryAreaAdr.AreaType.Equals(FinsMemoryAreaTypeEnum.HRBit))
                        {
                            List<bool> Result_BoolList = ByteList_BoolList(ResponseDataFrame);
                            return new FinsResult(Result_isSuccessed, Result_resultMessage, Result_commandFrame, Result_responseFrame, Result_BoolList);
                        }
                        else
                        {
                            string Result_String = ASCIIEncoding.ASCII.GetString(ResponseDataFrame.ToArray());
                            return new FinsResult(Result_isSuccessed, Result_resultMessage, Result_commandFrame, Result_responseFrame, Result_String);
                        }
                    }
                    else
                    {
                        Result_resultMessage = EndCodeContent;
                        return new FinsResult(Result_isSuccessed, Result_resultMessage, Result_commandFrame, Result_responseFrame);
                    }

                }
                else
                {
                    Result_isSuccessed = false;
                    Result_resultMessage = "接收回复报文出错";
                    return new FinsResult(Result_isSuccessed, Result_resultMessage);
                }
            }
            catch (Exception)
            {
                throw;
            }
        }


        /// <summary>
        /// FINS写入PLC内存指定区域方法（异步方法）
        /// </summary>
        /// <param name="IOMemoryAreaAdr">IO内存区域地址</param>
        /// <param name="finsFrameConfig">FINS帧参数设置</param>
        /// <param name="WriteCount">写入寄存器位数</param>
        /// <param name="WriteData">读取寄存器位数</param>
        /// <param name="UnitNO">单元号，默认"00"</param>
        /// <param name="ResponseWaitTime">回复时间(单位10ms)，默认0</param>
        /// <param name="connectType">连接方式，默认直连</param>
        /// <returns>EndCodeContent：返回结束代码含义（字符串格式），"0000"代表无异常，其他均为异常</returns>
        public async Task<FinsResult> Write_MemoryAreaAsync(FinsIOMemoryAreaAddress IOMemoryAreaAdr, FinsFrameConfig finsFrameConfig, ushort WriteCount, string WriteData, string UnitNO = "00", string ResponseWaitTime = "0", FinsConnectTypeEnum connectType = FinsConnectTypeEnum.Directly_Connect)
        {
            try
            {
                string EndCodeContent = null;
                List<byte> CommandFrame = new List<byte> { 0x40 };
                List<byte> ResponseFrame = new List<byte>();
                List<byte> MemoryAreaCode = new List<byte>();


                bool Result_isSuccessed;
                string Result_resultMessage;
                string Result_commandFrame;
                string Result_responseFrame;


                //定义内存区域代码
                if (IOMemoryAreaAdr != null)
                {
                    switch (IOMemoryAreaAdr.AreaType)
                    {
                        case FinsMemoryAreaTypeEnum.CIOBit:
                            MemoryAreaCode = FinsMemoryAreaCode.MemoryAreaCode_CIOBit;
                            break;
                        case FinsMemoryAreaTypeEnum.CIOWord:
                            MemoryAreaCode = FinsMemoryAreaCode.MemoryAreaCode_CIOWord;
                            break;
                        case FinsMemoryAreaTypeEnum.WRBit:
                            MemoryAreaCode = FinsMemoryAreaCode.MemoryAreaCode_WRBit;
                            break;
                        case FinsMemoryAreaTypeEnum.WRWord:
                            MemoryAreaCode = FinsMemoryAreaCode.MemoryAreaCode_WRWord;
                            break;
                        case FinsMemoryAreaTypeEnum.HRBit:
                            MemoryAreaCode = FinsMemoryAreaCode.MemoryAreaCode_HRBit;
                            break;
                        case FinsMemoryAreaTypeEnum.HRWord:
                            MemoryAreaCode = FinsMemoryAreaCode.MemoryAreaCode_HRWord;
                            break;
                        case FinsMemoryAreaTypeEnum.DMBit:
                            MemoryAreaCode = FinsMemoryAreaCode.MemoryAreaCode_DMBit;
                            break;
                        case FinsMemoryAreaTypeEnum.DMWord:
                            MemoryAreaCode = FinsMemoryAreaCode.MemoryAreaCode_DMWord;
                            break;
                        default:
                            throw new Exception("选择内存区域出错");
                    }
                }
                else
                {
                    throw new Exception("IOMemoryAreaAdr参数不存在");
                }

                //单元号
                CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(UnitNO));
                //FA
                CommandFrame.AddRange(new List<byte> { 0x46, 0x41 });
                //等待时间
                CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(ResponseWaitTime));

                //增加内存Fins命令帧参数
                if (finsFrameConfig != null)
                {
                    switch (connectType)
                    {
                        case FinsConnectTypeEnum.Directly_Connect:
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.ICF));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.DA2));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.SA2));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.SID));
                            break;
                        case FinsConnectTypeEnum.NetWork:
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.ICF));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.RSV));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.GCT));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.DNA));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.DA1));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.DA2));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.SNA));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.SA1));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.SA2));
                            CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(finsFrameConfig.SID));
                            break;
                        default:
                            throw new Exception("连接类型参数出错");
                    }
                }
                else
                {
                    throw new Exception("finsFrameConfig命令帧参数不存在");
                }

                //0102 写入代码
                CommandFrame.AddRange(new List<byte> { 0x30, 0x31, 0x30, 0x32 });
                //IO内存区域代码
                CommandFrame.AddRange(MemoryAreaCode);
                //内存起始(Word)地址
                CommandFrame.AddRange(Ushotr_X4String_ByteList(IOMemoryAreaAdr.WordAddress));
                //内存起始(Bit)地址
                CommandFrame.AddRange(Ushotr_X2String_ByteList(IOMemoryAreaAdr.BitAddress));
                //写入位数
                CommandFrame.AddRange(Ushotr_X4String_ByteList(WriteCount));
                //写入数据
                if (WriteData.Equals(string.Empty) || WriteData.Equals(null))
                {
                    throw new Exception("未输入数值");
                }
                else
                {
                    CommandFrame.AddRange(ASCIIEncoding.ASCII.GetBytes(WriteData));
                }
                //增加结束符，完成命令报文
                CommandFrame.AddRange(HostLinkCore.HostLinkEndCode(CommandFrame));

                //通信结果——命令帧
                Result_commandFrame = ASCIIEncoding.ASCII.GetString(CommandFrame.ToArray());



                //获取回复报文
                ResponseFrame = await HostLinkCore.HostLinkCommCoreAsync(serialPort, CommandFrame);

                Result_responseFrame = ASCIIEncoding.ASCII.GetString(ResponseFrame.ToArray());

                if (ResponseFrame != null)
                {
                    Result_isSuccessed = true;

                    //获取结束代码
                    switch (connectType)
                    {
                        case FinsConnectTypeEnum.Directly_Connect:
                            EndCodeContent = FinsEndCode.CatchEndCode(ResponseFrame, 19);
                            break;
                        case FinsConnectTypeEnum.NetWork:
                            EndCodeContent = FinsEndCode.CatchEndCode(ResponseFrame, 31);
                            break;
                        default:
                            throw new Exception("连接方式错误");
                    }
                    //返回通信结果（OK或NG信息）
                    if (EndCodeContent.Equals("0000"))
                    {
                        //确定通信结果信息
                        Result_resultMessage = "OK";
                        return new FinsResult(Result_isSuccessed, Result_resultMessage, Result_commandFrame, Result_responseFrame);
                    }
                    else
                    {
                        Result_resultMessage = EndCodeContent;
                        return new FinsResult(Result_isSuccessed, Result_resultMessage, Result_commandFrame, Result_responseFrame);
                    }
                }
                else
                {
                    Result_isSuccessed = false;
                    Result_resultMessage = "接收回复报文出错";
                    return new FinsResult(Result_isSuccessed, Result_resultMessage);
                }
            }
            catch (Exception)
            {
                throw;
            }
        }


        #endregion


    }
}
